﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using AChance.Bll.Func;
using AChance.Func;
using Dm;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;

namespace AChance.Dal.Func
{
    public static class DalSqlBase
    {
        public static class Name
        {
            public const string SQLSERVER = "SqlServer";
            public const string MYSQL = "MySql";
            public const string DM = "Dm";
        }
        public enum Type
        {
            SqlServer,
            MySql,
            Sqlite,
            Oracle,
            PostgreSQL,
            Dm
        }
        public static class Msg
        {
            public const string DDL_EXEC_FAIL = "相关DDL操作执行失败";
            public const string SELECT_EXEC_FAIL = "相关数据查询执行失败";
            public const string INSERT_EXEC_FAIL = "相关数据插入执行失败";
            public const string UPDATE_EXEC_FAIL = "相关数据更新执行失败";
            public const string DELETE_EXEC_FAIL = "相关数据删除执行失败";
            public const string NOT_FOUND = "相关数据未找到";

            private static List<string> _msgs = new List<string>();
            static Msg()
            {
                foreach (FieldInfo fieldInfo in typeof(Msg).GetFields())
                    if (fieldInfo.FieldType == typeof(string))
                        _msgs.Add((string)fieldInfo.GetValue(null));
            }
            public static bool Exists(string msg)
            {
                return _msgs.Contains(msg);
            }
            public static string Proc<T>(string msg) where T : class
            {
                return Proc(typeof(T), msg);
            }
            public static string Proc(System.Type entityType, string msg)
            {
                return msg.Insert(2, Exists(msg) ? DalEntity.GetDispName(entityType) : "");
            }
        }
        /// <summary>
        /// Sql参数化
        /// </summary>
        private class SqlArgs
        {
            /// <summary>
            /// 参数化后的Sql语句
            /// </summary>
            public string Sql { get; }
            /// <summary>
            /// 参数化后的所有参数
            /// </summary>
            public List<DbParameter> Args { get; }
            public SqlArgs(Type sqlType, string sql)
            {
                Sql = sql.Trim();
                Args = new List<DbParameter>();
                int no = 1;
                while (Sql.Contains(DalConst.SqlArg.PREFIX) && Sql.Contains(DalConst.SqlArg.SUFFIX))
                {
                    int headSite = Sql.IndexOf(DalConst.SqlArg.PREFIX);
                    int tailSite = Sql.IndexOf(DalConst.SqlArg.SUFFIX, headSite);
                    string name = $"@Arg_{no++:00}_";
                    string value = Sql.Substring(headSite, tailSite - headSite).Replace(DalConst.SqlArg.PREFIX, "").Replace(DalConst.SqlArg.SUFFIX, "");
                    Sql = Sql.Substring(0, headSite) + name + Sql.Substring(tailSite + DalConst.SqlArg.SUFFIX.Length);
                    DbParameter dbParameter;
                    switch (sqlType)
                    {
                        case Type.Dm:
                            dbParameter = new DmParameter(name, value);
                            break;
                        default:
                            dbParameter = new SqlParameter(name, value);
                            break;
                    }
                    Args.Add(dbParameter);
                }
            }
        }
        /// <summary>
        /// 获取当前线程的数据库操作实例
        /// </summary>
        internal static SqlOper GetSqlOper(string connectName)
        {
            return (SqlOper)FunTask.Context.SqlOper.GetOrAdd(connectName, CreateSqlOper(connectName));
        }
        /// <summary>
        /// 创建数据库操作实例
        /// </summary>
        internal static SqlOper CreateSqlOper(string connectName)
        {
            return CreateSqlOper(connectName, FunContext.AppSettings.Connect.SqlStrings[connectName]);
        }
        internal static SqlOper CreateSqlOper(string connectName, string connectString)
        {
            return new SqlOper(connectName switch
            {
                string name when name.StartsWith(Type.MySql.ToString()) => Type.MySql,
                string name when name.StartsWith(Type.Dm.ToString()) => Type.Dm,
                _ => Type.SqlServer
            }, connectString);
        }
        public class SqlOper
        {
            private readonly Type _sqlType;
            private readonly string _connectString;
            public SqlOper(Type sqlType, string connectString)
            {
                _sqlType = sqlType;
                _connectString = connectString;
            }
            /// <summary>
            /// 扩展操作
            /// </summary>
            public DalSqlContext Ext { get; private set; }

            #region 开关
            /// <summary>
            /// 打开数据库操作
            /// </summary>
            public void Open(bool beginTran = false)
            {
                if (Ext != null)
                    throw new Exception("当前数据库操作还未关闭，无法再次打开");
                Ext = new DalSqlContext(_sqlType, _connectString);
                if (beginTran)
                    BeginTran();
                else
                    RollbackTran();
            }
            /// <summary>
            /// 关闭数据库操作
            /// </summary>
            public void Close(bool commitTran = false)
            {
                if (commitTran)
                    CommitTran();
                else
                    RollbackTran();
                Ext?.Dispose();
                Ext = null;
            }
            #endregion

            #region 事务
            /// <summary>
            /// 启动事务
            /// </summary>
            public void BeginTran()
            {
                if (Ext.Database.CurrentTransaction is null)
                    Ext.Database.BeginTransaction();
            }
            /// <summary>
            /// 提交事务
            /// </summary>
            public void CommitTran()
            {
                Ext?.Database.CurrentTransaction?.Commit();
            }
            /// <summary>
            /// 回滚事务
            /// </summary>
            public void RollbackTran()
            {
                Ext?.Database.CurrentTransaction?.Rollback();
            }
            #endregion

            #region 执行
            /// <summary>
            /// 执行数据库操作，并对结果进行统一处理
            /// </summary>
            private TResult Exec<TResult>(Func<TResult> oper, string execFailMsg = null)
            {
                return Exec<object, TResult>(oper, execFailMsg);
            }
            /// <summary>
            /// 执行数据库操作，并对结果进行统一处理
            /// </summary>
            private TResult Exec<T, TResult>(Func<TResult> oper, string execFailMsg = null) where T : class
            {
                try
                {
                    return oper();
                }
                catch (Exception ex)
                {
                    FunLogs.LogErrorForSqlExec(ex);
                    //执行失败后的消息处理
                    if (!execFailMsg.IsNullOrEmpty())
                        throw new Exception(Msg.Proc<T>(execFailMsg));
                    return default;
                }
                finally
                {
                    //取消DbContext中所有被跟踪的实体
                    while (Ext.ChangeTracker.Entries().Count() > 0)
                        Ext.ChangeTracker.Entries().FirstOrDefault().State = EntityState.Detached;
                }
            }
            /// <summary>
            /// 执行DDL操作，主要用于维护数据结构、索引、视图、存储过程、触发器等方面的操作
            /// </summary>
            public bool ExecDDL(string sql, string execFailMsg = Msg.DDL_EXEC_FAIL)
            {
                return Exec(() => { Ext.Database.ExecuteSqlRaw(sql, new object[] { }); return true; }, execFailMsg);
            }
            #endregion

            #region 查询
            #region Select
            /// <summary>
            /// 查询一条数据(根据主键)
            /// </summary>
            public T Select<T>(string key, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                var result = Exec<T, T>(() => Ext.Set<T>().Find(key), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(Msg.Proc<T>(notFoundMsg));
                return result;
            }
            /// <summary>
            /// 查询一条数据(根据主键)
            /// </summary>
            public object Select(string key, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                var entityType = DalEntity.GetTypeByKey(key);
                var result = Exec(() => Ext.Find(entityType, key), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(Msg.Proc(entityType, notFoundMsg));
                return result;
            }
            /// <summary>
            /// 查询一条数据(根据主键)
            /// </summary>
            public T Select<T>(T entity, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                var result = Exec<T, T>(() => Ext.Entry(entity).GetDatabaseValues()?.ToObject() as T, execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(Msg.Proc<T>(notFoundMsg));
                return result;
            }
            #endregion

            #region SelectRange
            /// <summary>
            /// 查询一条或多条数据(根据Sql)
            /// </summary>
            public List<T> SelectRange<T>(string sql, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var result = Exec<T, List<T>>(() => Ext.Set<T>().FromSqlRaw(sqlArgs.Sql, sqlArgs.Args).ToList(), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result.IsNullOrEmpty())
                    throw new Exception(Msg.Proc<T>(notFoundMsg));
                return result;
            }
            /// <summary>
            /// 查询一条或多条数据(根据条件)
            /// </summary>
            public List<T> SelectRange<T>(Expression<Func<T, bool>> where, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                var result = Exec<T, List<T>>(() => Ext.Set<T>().Where(where).ToList(), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result.IsNullOrEmpty())
                    throw new Exception(Msg.Proc<T>(notFoundMsg));
                return result;
            }
            #endregion

            #region SelectAll
            /// <summary>
            /// 查询表中的所有数据
            /// </summary>
            public List<T> SelectAll<T>(string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, List<T>>(() => Ext.Set<T>().ToList(), execFailMsg);
            }
            #endregion

            #region SelectFirst
            /// <summary>
            /// 查询第一条数据(根据条件)
            /// </summary>
            public T SelectFirst<T>(Expression<Func<T, bool>> where, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                var result = Exec<T, T>(() => Ext.Set<T>().FirstOrDefault(where), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(Msg.Proc<T>(notFoundMsg));
                return result;
            }
            #endregion

            #region SelectCount
            /// <summary>
            /// 查询总记录数(根据Sql)
            /// </summary>
            public int SelectCount(string sql, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var gather = Exec(() => Ext.Database.ExecuteReader((new DalQuery.Proc()).GetSql(_sqlType, sqlArgs.Sql, DalQuery.Proc.Type.Gather), sqlArgs.Args.ToArray()), execFailMsg);
                return Convert.ToInt32(gather.Rows[0][nameof(DalQuery.Result.TotalNumber)]);
            }
            /// <summary>
            /// 查询总记录数
            /// </summary>
            public int SelectCount<T>(string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() => Ext.Set<T>().Count(), execFailMsg);
            }
            /// <summary>
            /// 查询总记录数(根据条件)
            /// </summary>
            public int SelectCount<T>(Expression<Func<T, bool>> where, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() => Ext.Set<T>().Count(where), execFailMsg);
            }
            #endregion

            #region SelectExists
            /// <summary>
            /// 查询数据是否存在(根据Sql)
            /// </summary>
            public bool SelectExists(string sql, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                return SelectCount(sql, execFailMsg) > 0;
            }
            /// <summary>
            /// 查询数据是否存在(根据主键)
            /// </summary>
            public bool SelectExists<T>(T entity, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, T>(() => Ext.Entry(entity).GetDatabaseValues()?.ToObject() as T, execFailMsg) != null;
            }
            /// <summary>
            /// 查询数据是否存在(根据条件)
            /// </summary>
            public bool SelectExists<T>(Expression<Func<T, bool>> where, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                return SelectCount(where, execFailMsg) > 0;
            }
            #endregion

            #region SelectOther
            /// <summary>
            /// 查询数据，可加工(根据Sql)
            /// </summary>
            public DalQuery.Result SelectProc(string sql, DalQuery.Proc queryProc, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                queryProc ??= new DalQuery.Proc();
                var result = new DalQuery.Result();
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var gather = Exec(() => Ext.Database.ExecuteReader(queryProc.GetSql(_sqlType, sqlArgs.Sql, DalQuery.Proc.Type.Gather), sqlArgs.Args.ToArray()), execFailMsg);
                var gatherRow = gather.Rows[0];
                result.TotalNumber = Convert.ToInt32(gatherRow[nameof(DalQuery.Result.TotalNumber)]);
                if (!notFoundMsg.IsNullOrEmpty() && result.TotalNumber.IsZero())
                    throw new Exception(notFoundMsg);
                if (!queryProc.SelectSum.IsNullOrEmpty())
                    foreach (var condition in queryProc.SelectSum)
                    {
                        var name = condition.Alias.IsNullOrEmpty() ? condition.Name : condition.Alias;
                        result.DataSum.Add(name, gatherRow[name]);
                    }
                result.DataList = Exec(() => Ext.Database.ExecuteReader(queryProc.GetSql(_sqlType, sqlArgs.Sql, DalQuery.Proc.Type.Page), sqlArgs.Args.ToArray()), execFailMsg);
                result.PageIndex = queryProc.PageIndex;
                result.PageSize = queryProc.PageSize;
                result.TotalPage = (result.TotalNumber <= 0 || result.PageSize <= 0) ? 0 : (int)Math.Ceiling((double)result.TotalNumber / result.PageSize);
                return result;
            }
            /// <summary>
            /// 查询数据，返回一个DataTable类型的结果(根据Sql)
            /// </summary>
            public DataTable SelectTable(string sql, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var result = Exec(() => Ext.Database.ExecuteReader(sqlArgs.Sql, sqlArgs.Args.ToArray()), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result.IsNullOrEmpty())
                    throw new Exception(notFoundMsg);
                return result;
            }
            /// <summary>
            /// 查询数据，返回一个Int类型的结果(根据Sql)
            /// </summary>
            public int SelectInt(string sql, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var result = Exec(() => Ext.Database.ExecuteScalar(sqlArgs.Sql, sqlArgs.Args.ToArray()), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(notFoundMsg);
                try
                {
                    return Convert.ToInt32(result);
                }
                catch
                {
                    return notFoundMsg.IsNullOrEmpty() ? default(int) : throw new Exception(notFoundMsg);
                }
            }
            /// <summary>
            /// 查询数据，返回一个Double类型的结果(根据Sql)
            /// </summary>
            public double SelectDouble(string sql, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var result = Exec(() => Ext.Database.ExecuteScalar(sqlArgs.Sql, sqlArgs.Args.ToArray()), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(notFoundMsg);
                try
                {
                    return Convert.ToDouble(result);
                }
                catch
                {
                    return notFoundMsg.IsNullOrEmpty() ? default(double) : throw new Exception(notFoundMsg);
                }
            }
            /// <summary>
            /// 查询数据，返回一个String类型的结果(根据Sql)
            /// </summary>
            public string SelectString(string sql, string notFoundMsg = Msg.NOT_FOUND, string execFailMsg = Msg.SELECT_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                var result = Exec(() => Ext.Database.ExecuteScalar(sqlArgs.Sql, sqlArgs.Args.ToArray()), execFailMsg);
                if (!notFoundMsg.IsNullOrEmpty() && result is null)
                    throw new Exception(notFoundMsg);
                try
                {
                    return Convert.ToString(result);
                }
                catch
                {
                    return notFoundMsg.IsNullOrEmpty() ? default(string) : throw new Exception(notFoundMsg);
                }
            }
            #endregion
            #endregion

            #region 插入
            #region Insert
            /// <summary>
            /// 插入一条数据
            /// </summary>
            public int Insert<T>(T entity, string execFailMsg = Msg.INSERT_EXEC_FAIL) where T : class, new()
            {
                DalEntity.RepairDefault(entity);
                return Exec<T, int>(() => { Ext.Set<T>().Add(entity); return Ext.SaveChanges(); }, execFailMsg);
            }
            #endregion

            #region InsertRange
            /// <summary>
            /// 插入一条或多条数据(根据Sql)
            /// </summary>
            public int InsertRange(string sql, string execFailMsg = Msg.INSERT_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                return Exec(() => Ext.Database.ExecuteSqlRaw(sqlArgs.Sql, sqlArgs.Args), execFailMsg);
            }
            /// <summary>
            /// 插入一条或多条数据
            /// </summary>
            public int InsertRange<T>(List<T> entities, string execFailMsg = Msg.INSERT_EXEC_FAIL) where T : class, new()
            {
                DalEntity.RepairDefaultRange(entities);
                return Exec<T, int>(() => { Ext.Set<T>().AddRange(entities); return Ext.SaveChanges(); }, execFailMsg);
            }
            #endregion
            #endregion

            #region 更新
            #region Update
            /// <summary>
            /// 更新一条数据(根据主键)，不会更新值为null的字段
            /// </summary>
            public int Update<T>(T entity, string execFailMsg = Msg.UPDATE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() =>
                {
                    Ext.Set<T>().Attach(entity);
                    foreach (PropertyEntry propertyEntry in Ext.Entry(entity).Properties)
                        if (propertyEntry.CurrentValue != null && !propertyEntry.Metadata.IsPrimaryKey())
                            propertyEntry.IsModified = true;
                    return Ext.SaveChanges();
                }, execFailMsg);
            }
            /// <summary>
            /// 更新一条数据中的指定字段(根据主键)，不会更新值为null的字段
            /// </summary>
            public int Update<T>(T entity, Expression<Func<T, object>> columns, string execFailMsg = Msg.UPDATE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() =>
                {
                    var updateFields = new List<string>();
                    switch (columns.Body)
                    {
                        case MemberExpression body:
                            updateFields.Add(body.Member.Name);
                            break;
                        case NewExpression body:
                            body.Members?.ToList().ForEach(memberInfo => updateFields.Add(memberInfo.Name));
                            break;
                    }
                    if (updateFields.Count.IsZero())
                        return 0;
                    Ext.Set<T>().Attach(entity);
                    foreach (PropertyEntry propertyEntry in Ext.Entry(entity).Properties)
                        if (updateFields.Contains(propertyEntry.Metadata.Name))
                            if (propertyEntry.CurrentValue != null && !propertyEntry.Metadata.IsPrimaryKey())
                                propertyEntry.IsModified = true;
                    return Ext.SaveChanges();
                }, execFailMsg);
            }
            #endregion

            #region UpdateRange
            /// <summary>
            /// 更新一条或多条数据(根据Sql)
            /// </summary>
            public int UpdateRange(string sql, string execFailMsg = Msg.UPDATE_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                return Exec(() => Ext.Database.ExecuteSqlRaw(sqlArgs.Sql, sqlArgs.Args), execFailMsg);
            }
            /// <summary>
            /// 更新一条或多条数据(根据主键)，不会更新值为null的字段
            /// </summary>
            public int UpdateRange<T>(List<T> entities, string execFailMsg = Msg.UPDATE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() =>
                {
                    Ext.Set<T>().AttachRange(entities);
                    foreach (T entity in entities)
                        foreach (PropertyEntry propertyEntry in Ext.Entry(entity).Properties)
                            if (propertyEntry.CurrentValue != null && !propertyEntry.Metadata.IsPrimaryKey())
                                propertyEntry.IsModified = true;
                    return Ext.SaveChanges();
                }, execFailMsg);
            }
            /// <summary>
            /// 更新一条或多条数据中的指定字段(根据主键)，不会更新值为null的字段
            /// </summary>
            public int UpdateRange<T>(List<T> entities, Expression<Func<T, object>> columns, string execFailMsg = Msg.UPDATE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() =>
                {
                    var updateFields = new List<string>();
                    switch (columns.Body)
                    {
                        case MemberExpression body:
                            updateFields.Add(body.Member.Name);
                            break;
                        case NewExpression body:
                            body.Members?.ToList().ForEach(memberInfo => updateFields.Add(memberInfo.Name));
                            break;
                    }
                    if (updateFields.Count.IsZero())
                        return 0;
                    Ext.Set<T>().AttachRange(entities);
                    foreach (T entity in entities)
                        foreach (PropertyEntry propertyEntry in Ext.Entry(entity).Properties)
                            if (updateFields.Contains(propertyEntry.Metadata.Name))
                                if (propertyEntry.CurrentValue != null && !propertyEntry.Metadata.IsPrimaryKey())
                                    propertyEntry.IsModified = true;
                    return Ext.SaveChanges();
                }, execFailMsg);
            }
            /// <summary>
            /// 更新一条或多条数据中的指定字段(根据条件)，不会更新值为null的字段
            /// </summary>
            public int UpdateRange<T>(Expression<Func<T, T>> columns, Expression<Func<T, bool>> where, string execFailMsg = Msg.UPDATE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() =>
                {
                    Ext.Set<T>().AsTracking().Where(where).ToList().ForEach(entity =>
                    {
                        var entityColumns = columns.Compile()(entity);
                        foreach (PropertyEntry propertyEntry in Ext.Entry(entity).Properties)
                        {
                            var value = propertyEntry.Metadata.PropertyInfo.GetValue(entityColumns);
                            if (value != null && !propertyEntry.Metadata.IsPrimaryKey())
                                propertyEntry.CurrentValue = value;
                        }
                    });
                    return Ext.SaveChanges();
                }, execFailMsg);
            }
            #endregion
            #endregion

            #region 删除
            #region Delete
            /// <summary>
            /// 删除一条数据(根据主键)
            /// </summary>
            public int Delete<T>(string key, string execFailMsg = Msg.DELETE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() => { Ext.Set<T>().Remove(Ext.Set<T>().Find(key)); return Ext.SaveChanges(); }, execFailMsg);
            }
            /// <summary>
            /// 删除一条数据(根据主键)
            /// </summary>
            public int Delete<T>(T entity, string execFailMsg = Msg.DELETE_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() => { Ext.Set<T>().Remove(entity); return Ext.SaveChanges(); }, execFailMsg);
            }
            #endregion

            #region DeleteRange
            /// <summary>
            /// 删除一条或多条数据(根据Sql)
            /// </summary>
            public int DeleteRange(string sql, string execFailMsg = Msg.DELETE_EXEC_FAIL)
            {
                var sqlArgs = new SqlArgs(_sqlType, sql);
                return Exec(() => Ext.Database.ExecuteSqlRaw(sqlArgs.Sql, sqlArgs.Args), execFailMsg);
            }
            /// <summary>
            /// 删除一条或多条数据(根据主键)
            /// </summary>
            public int DeleteRange<T>(List<T> entities, string execFailMsg = Msg.INSERT_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() => { Ext.Set<T>().RemoveRange(entities); return Ext.SaveChanges(); }, execFailMsg);
            }
            /// <summary>
            /// 删除一条或多条数据(根据条件)
            /// </summary>
            public int DeleteRange<T>(Expression<Func<T, bool>> where, string execFailMsg = Msg.SELECT_EXEC_FAIL) where T : class, new()
            {
                return Exec<T, int>(() => { Ext.Set<T>().RemoveRange(Ext.Set<T>().Where(where).ToList()); return Ext.SaveChanges(); }, execFailMsg);
            }
            #endregion
            #endregion


        }
    }
}
